/* 
*  Copyright (C) 2009-2010 WCG Project
*
*  This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by the
*  Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software Foundation,
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*  In addition, as a special exception, the author gives permission to
*  link the code of this program with the Half-Life Game Engine ("HL
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
*  respects for all of the code used other than the HL Engine and MODs
*  from Valve. If you modify this file, you may extend this exception
*  to your version of the file, but you are not obligated to do so. If
*  you do not wish to do so, delete this exception statement from your
*  version.
*/




// CS Offsets (win32)
#define OFFSET_CSTEAMS			114
#define OFFSET_CSMONEY			115
#define OFFSET_NVGOGGLES		129
#define OFFSET_ZOOMTYPE			363
#define OFFSET_CSDEATHS			444
#define OFFSET_AWM_AMMO			377 
#define OFFSET_SCOUT_AMMO		378
#define OFFSET_PARA_AMMO		379
#define OFFSET_FAMAS_AMMO		380
#define OFFSET_M3_AMMO			381
#define OFFSET_USP_AMMO			382
#define OFFSET_FIVESEVEN_AMMO	383
#define OFFSET_DEAGLE_AMMO		384
#define OFFSET_P228_AMMO		385
#define OFFSET_GLOCK_AMMO		386
#define OFFSET_FLASH_AMMO		387
#define OFFSET_HE_AMMO			388
#define OFFSET_SMOKE_AMMO		389
#define OFFSET_C4_AMMO			390
#define OFFSET_CLIPAMMO			51
#define OFFSET_MODELINDEX		491 // by Orangutanz

#define OFFSET_LINUX			5 // offsets 5 higher in Linux builds
#define OFFSET_LINUX_WEAPONS	4 // weapon offsets are only 4 steps higher on Linux

// Ammo Offsets for weapons
new const AMMOOFFSET[] = { -1, OFFSET_P228_AMMO, -1, OFFSET_SCOUT_AMMO, OFFSET_HE_AMMO, OFFSET_M3_AMMO, OFFSET_C4_AMMO,
			OFFSET_USP_AMMO, OFFSET_FAMAS_AMMO, OFFSET_SMOKE_AMMO, OFFSET_GLOCK_AMMO, OFFSET_FIVESEVEN_AMMO,
			OFFSET_USP_AMMO, OFFSET_FAMAS_AMMO, OFFSET_FAMAS_AMMO, OFFSET_FAMAS_AMMO, OFFSET_USP_AMMO,
			OFFSET_GLOCK_AMMO, OFFSET_AWM_AMMO, OFFSET_GLOCK_AMMO, OFFSET_PARA_AMMO, OFFSET_M3_AMMO,
			OFFSET_FAMAS_AMMO, OFFSET_GLOCK_AMMO, OFFSET_SCOUT_AMMO, OFFSET_FLASH_AMMO, OFFSET_DEAGLE_AMMO,
			OFFSET_FAMAS_AMMO, OFFSET_SCOUT_AMMO, -1, OFFSET_FIVESEVEN_AMMO }


#define FixedUnsigned16(%1,%2) clamp(floatround(%1 * float(%2)), 0, 0xffff);
//stock FixedUnsigned16( Float:value, Float:scale )
//{
//	new output = floatround( value * scale )
//
//	if( output < 0 )
//		output = 0
//	else if( output > 0xFFFF )
//		output = 0xFFFF
//
//	return output
//}



#define FixedSigned16(%1,%2) clamp(floatround(%1 * float(%2)), -32768, 32767);
//stock FixedSigned16( Float:value, Float:scale )
//{
//	new output = floatround( value * scale )
//
//	if( output > 32767 )
//		output = 32767
//	else if( output < -32768 )
//		output = -32768
//
//	return output
//}



#define GetTaskID(%1,%2) ( %1 >= %2 ) ? ( %1 - %2 ) : %1;
//stock GetTaskID( id, TaskID )
//{
//	if( id >= TaskID )
//		id -= TaskID
//
//	return id
//}




stock fm_find_sphere_class( aroundent, const _lookforclassname[], Float:radius, entlist[], maxents, const Float:_origin[3] )
{
	static Float:origin[3]

	if( !pev_valid( aroundent ) )
	{
		origin[0] = _origin[0]
		origin[1] = _origin[1]
		origin[2] = _origin[2]
	}
	else
		pev( aroundent, pev_origin, origin )

	new ent = aroundent, foundents = 0
	while( (ent = fm_find_ent_in_sphere( ent, origin, radius) ) != 0 )
	{
		if( !pev_valid( ent ) )
			continue

		if( foundents >= maxents )
			break

		static classname[32]
		pev( ent, pev_classname, classname, 31 )

		if( equal( classname, _lookforclassname ) )
			entlist[foundents++] = ent
	}
	return foundents
}



#define fm_get_user_team(%1) get_pdata_int(%1, OFFSET_CSTEAMS, OFFSET_LINUX);
//stock fm_get_user_team(id)
//	return get_pdata_int(id, OFFSET_CSTEAMS, OFFSET_LINUX)



#define fm_set_user_team(%1) set_pdata_int(%1, OFFSET_CSTEAMS, team, OFFSET_LINUX);
//stock fm_set_user_team(id, team)
//	set_pdata_int(id, OFFSET_CSTEAMS, team, OFFSET_LINUX)



// Get User BP Ammo
stock fm_get_user_bpammo(id, iWeaponID)
	return get_pdata_int(id, AMMOOFFSET[iWeaponID], OFFSET_LINUX)



// Set User BP Ammo
stock fm_set_user_bpammo(id, iWeaponID, iAmount = -1)
{
	if( iAmount < 0 )
	{
		// Max BP ammo for weapons
		new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
			30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }

		iAmount = MAXBPAMMO[iWeaponID]
	}

	set_pdata_int(id, AMMOOFFSET[iWeaponID], iAmount, OFFSET_LINUX)
}



// Set Weapon Clip Ammo
stock fm_set_weapon_ammo(entity, amount)
	set_pdata_int(entity, OFFSET_CLIPAMMO, amount, OFFSET_LINUX_WEAPONS)



// Get Weapon Clip Ammo
stock fm_get_weapon_ammo(entity)
	return get_pdata_int(entity, OFFSET_CLIPAMMO, OFFSET_LINUX_WEAPONS)



// Set User Zoom
stock fm_remove_user_zoom(id)
	set_pdata_int(id, OFFSET_ZOOMTYPE, 90, OFFSET_LINUX)



// Get User Deaths
stock fm_get_user_deaths(id)
	return get_pdata_int(id, OFFSET_CSDEATHS, OFFSET_LINUX)



// Set User Deaths
stock fm_set_user_deaths(id, value)
	set_pdata_int(id, OFFSET_CSDEATHS, value, OFFSET_LINUX)



//-------------------------------------------
// fm_reset_user_velocity
//
//-------------------------------------------
stock fm_reset_user_velocity( id )
{
	set_pev( id, pev_velocity, {0.0, 0.0, 0.0}  )
	set_pev( id, pev_basevelocity, {0.0, 0.0, 0.0} )
	set_pev( id, pev_clbasevelocity, {0.0, 0.0, 0.0} )
	set_pev( id, pev_avelocity, {0.0, 0.0, 0.0} )
	set_pev( id, pev_flFallVelocity, 0.0 )

	set_pev( id, pev_oldbuttons, 0 )
	set_pev( id, pev_button, 0 )
}


stock Create_TE_TEXTMESSAGE( id=0, red=200, green=100, blue=0, alpha=255, Float:x=-1.0, Float:y=0.35, effect=0, Float:fxTime=6.0, Float:holdTime=12.0, Float:fadeinTime=0.1, Float:fadeoutTime=0.2, channel=4, message[], any:... )
{
	static buffer[512]

	vformat( buffer, 511, message, 15 )
	
	if( id )
		message_begin( MSG_ONE, SVC_TEMPENTITY, _, id )
	else
		message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	
	write_byte( TE_TEXTMESSAGE )
	write_byte( channel & 255 )
	write_short( FixedSigned16( x, float(1<<13) ) )
	write_short( FixedSigned16( y, float(1<<13) ) )
	write_byte( effect )
	write_byte( red )
	write_byte( green )
	write_byte( blue )
	write_byte( alpha )
	write_byte( 255 )
	write_byte( 255 )
	write_byte( 255 )
	write_byte( alpha )
	write_short( FixedUnsigned16( fadeinTime, (1<<8) ) )
	write_short( FixedUnsigned16( fadeoutTime, (1<<8) ) )
	write_short( FixedUnsigned16( holdTime, (1<<8) ) )

	if( effect == 2 )
		write_short( FixedUnsigned16( fxTime, (1<<8) ) )
	
	write_string( buffer )
	message_end()
}



stock Create_TE_Smoke(originSight[3], position[3], iSprite, scale, framerate)
{
	message_begin( MSG_PVS, SVC_TEMPENTITY, originSight )
	write_byte( TE_SMOKE )
	write_coord( position[0] )			// Position
	write_coord( position[1] )
	write_coord( position[2] )
	write_short( iSprite )				// Sprite index
	write_byte( scale )					// scale * 10
	write_byte( framerate  )			// framerate
	message_end()
}



stock Create_DeathMsg_CS(killer_id,victim_id,headshot,weaponname[])
{
	message_begin(MSG_ALL,gmsgDeathMsg)
	write_byte(killer_id)
	write_byte(victim_id)
	write_byte(headshot)
	write_string(weaponname)
	message_end()
}




stock Create_TE_BEAMCYLINDER(origin[3], center[3], axis[3], iSprite, startFrame, frameRate, life, width, amplitude, red, green, blue, brightness, speed)
{
	message_begin( MSG_PAS, SVC_TEMPENTITY, origin )
	write_byte( TE_BEAMCYLINDER )
	write_coord( center[0] )			// center position (X)
	write_coord( center[1] )			// center position (Y)
	write_coord( center[2] )			// center position (Z)
	write_coord( axis[0] )				// axis and radius (X)
	write_coord( axis[1] )				// axis and radius (Y)
	write_coord( axis[2] )				// axis and radius (Z)
	write_short( iSprite )				// sprite index
	write_byte( startFrame )			// starting frame
	write_byte( frameRate )				// frame rate in 0.1's
	write_byte( life )					// life in 0.1's
	write_byte( width )					// line width in 0.1's
	write_byte( amplitude )				// noise amplitude in 0.01's
	write_byte( red )					// color (red)
	write_byte( green )					// color (green)
	write_byte( blue )					// color (blue)
	write_byte( brightness )			// brightness
	write_byte( speed )					// scroll speed in 0.1's
	message_end()
}


stock Create_TE_EXPLOSION( origin[3], origin2[3], iSprite, scale, frameRate, flags )
{
	message_begin( MSG_PVS, SVC_TEMPENTITY, origin )
	write_byte( TE_EXPLOSION )
	write_coord( origin2[0] )			// position (X)
	write_coord( origin2[1] )			// position (Y)
	write_coord( origin2[2]	)			// position (Z)
	write_short( iSprite )				// sprite index
	write_byte( scale )					// scale in 0.1's
	write_byte( frameRate )				// framerate
	write_byte( flags )					// flags
	message_end()

//#define TE_EXPLFLAG_NONE			0	// all flags clear makes default Half-Life explosion
//#define TE_EXPLFLAG_NOADDITIVE	1	// sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite)
//#define TE_EXPLFLAG_NODLIGHTS		2	// do not render dynamic lights
//#define TE_EXPLFLAG_NOSOUND		4	// do not play client explosion sound
//#define TE_EXPLFLAG_NOPARTICLES	8	// do not draw particles

}


stock Create_TE_FIREFIELD( origin[3], radius, iSprite, count, flags, duration )
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_FIREFIELD)
	write_coord(origin[0])
	write_coord(origin[1])
	write_coord(origin[2])
	write_short(radius)
	write_short(iSprite)
	write_byte(count)
	write_byte(flags)
	write_byte(duration)
	message_end()

// Flags
//#define TEFIRE_FLAG_ALLFLOAT        1        // All sprites will drift upwards as they animate
//#define TEFIRE_FLAG_SOMEFLOAT       2        // Some of the sprites will drift upwards. (50% chance)
//#define TEFIRE_FLAG_LOOP            4        // If set, sprite plays at 15 fps, otherwise plays at whatever rate stretches the animation over the sprite's duration.
//#define TEFIRE_FLAG_ALPHA           8        // If set, sprite is rendered alpha blended at 50% else, opaque
//#define TEFIRE_FLAG_PLANAR          16       // If set, all fire sprites have same initial Z instead of randomly filling a cube. 
}


stock Create_TE_SPRITE_SPRAY( origin[3], velocity[3], iSprite, count, speed, noise )
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_SPRITE_SPRAY)
	write_coord(origin[0])
	write_coord(origin[1])
	write_coord(origin[2])
	write_coord(velocity[0])
	write_coord(velocity[1])
	write_coord(velocity[2])
	write_short(iSprite)
	write_byte(count)
	write_byte(speed)
	write_byte(noise)
	message_end()
}


stock Create_ScreenShake(id, amount, duration, frequency)
{

	message_begin(MSG_ONE,gmsgScreenShake,{0,0,0},id) 
	write_short( amount )				// ammount 
	write_short( duration )				// lasts this long 
	write_short( frequency )			// frequency
	message_end()
}


stock Create_ScoreInfo(id,frags,deaths,playerClass,team )
{
	message_begin(MSG_ALL,gmsgScoreInfo)
	write_byte(id)
	write_short(frags)
	write_short(deaths)
	write_short(playerClass)
	write_short(team)
	message_end()
}



stock Create_TE_SPRITETRAIL(start[3], end[3], iSprite, count, life, scale, velocity, random )
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte( TE_SPRITETRAIL )
	write_coord( start[0] )				// start position (X)
	write_coord( start[1] )				// start position (Y)
	write_coord( start[2] )				// start position (Z)
	write_coord( end[0] )				// end position (X)
	write_coord( end[1] )				// end position (Y)
	write_coord( end[2] )				// end position (Z)
	write_short( iSprite )				// sprite index
	write_byte( count )					// count
	write_byte( life)					// life in 0.1's
	write_byte( scale)					// scale in 0.1's
	write_byte( velocity )				// velocity along vector in 10's
	write_byte( random )				// randomness of velocity in 10's
	message_end()
}



stock Create_TE_DLIGHT(origin[3], radius, red, green, blue, life, decayRate )
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_DLIGHT )
	write_coord( origin[0] )
	write_coord( origin[1] )
	write_coord( origin[2] )
	write_byte( radius )
	write_byte( red )
	write_byte( green )
	write_byte( blue )
	write_byte( life )
	write_byte( decayRate )
	message_end()
}



stock Create_StatusText(id, linenumber, text[])
{
	message_begin( MSG_ONE, gmsgStatusText, _, id )
	write_byte( linenumber )			// line number of status bar text
	write_string( text )				// status bar text
	message_end()
}



stock Create_SayText(id, text[])
{
	message_begin( MSG_ONE, gmsgSayText, _, id )
	write_byte( id )
	write_string( text )
	message_end()
}



stock Create_ItemPickupText( id, text[] )
{
	message_begin( MSG_ONE, gmsgItemPickup, _, id )
	write_string( text )
	message_end()
}



stock Create_TextMsg( id, duration, text[] )
{
	message_begin( MSG_ONE, gmsgTextMsg, _, id )
	write_byte( duration )
	write_string( text )
	message_end()
}



stock Create_BarTime(id, duration, flag)
{
	message_begin( MSG_ONE, gmsgBarTime, _, id )
	write_byte( duration ) // duration 
	write_byte( flag )
	message_end() 
}



stock Create_TE_BEAMFOLLOW(entity, iSprite, life, width, red, green, blue, alpha)
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_BEAMFOLLOW )
	write_short( entity )			// entity
	write_short( iSprite )			// model
	write_byte( life )				// life
	write_byte( width )				// width
	write_byte( red )				// red
	write_byte( green )				// green
	write_byte( blue )				// blue
	write_byte( alpha )				// brightness
	message_end()
}



stock Create_TE_BEAMPOINTS(start[3], end[3], iSprite, startFrame, frameRate, life, width=10, noise=0, rgba_color=0xffffff, speed=0)
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_BEAMPOINTS )
	write_coord( start[0] )
	write_coord( start[1] )
	write_coord( start[2] )
	write_coord( end[0] )
	write_coord( end[1] )
	write_coord( end[2] )
	write_short( iSprite )			// model
	write_byte( startFrame )		// start frame
	write_byte( frameRate )			// framerate
	write_byte( life )				// life
	write_byte( width )				// width
	write_byte( noise )				// noise
	write_byte( COLOR_RED(rgba_color) )
	write_byte( COLOR_GREEN(rgba_color) )
	write_byte( COLOR_BLUE(rgba_color) )
	write_byte( COLOR_ALPHA(rgba_color) )		// brightness
	write_byte( speed )				// speed
	message_end()
}



stock Create_TE_BEAMENTS(startEntity, endEntity, iSprite, startFrame, frameRate, life, width, noise, red, green, blue, alpha, speed)
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_BEAMENTS )
	write_short( startEntity )		// start entity
	write_short( endEntity )		// end entity
	write_short( iSprite )			// model
	write_byte( startFrame )		// starting frame
	write_byte( frameRate )			// frame rate
	write_byte( life )				// life
	write_byte( width )				// line width
	write_byte( noise )				// noise amplitude
	write_byte( red )				// red
	write_byte( green )				// green
	write_byte( blue )				// blue
	write_byte( alpha )				// brightness
	write_byte( speed )				// scroll speed
	message_end()
}



stock Create_TE_ELIGHT(entity, start[3], radius, red, green, blue, life, decayRate)
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_ELIGHT )
	write_short( entity )			// entity
	write_coord( start[0] )			// initial position
	write_coord( start[1] )			// initial position
	write_coord( start[2] )			// initial position
	write_coord( radius )			// radius
	write_byte( red )				// red
	write_byte( green )				// green
	write_byte( blue )				// blue
	write_byte( life )				// life
	write_coord( decayRate )		// decay rate
	message_end()
}



stock Create_TE_SPRAY(position[3], direction[3], iSprite, count, speed, noise, rendermode)
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY ) 
	write_byte( TE_SPRAY )
	write_coord( position[0] )		// Position
	write_coord( position[1] ) 
	write_coord( position[2] ) 
	write_coord( direction[0] )		// Direction 
	write_coord( direction[1] )  
	write_coord( direction[2] ) 
	write_short( iSprite )			// Sprite
	write_byte( count )				// count 
	write_byte( speed )				// speed 
	write_byte( noise )				// noise
	write_byte( rendermode )		// rendermode
	message_end() 
}



stock Create_TE_SPRITE(position[3], iSprite, scale, alpha)
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY ) 
	write_byte( TE_SPRITE ) 
	write_coord( position[0] )		// position)
	write_coord( position[1] ) 
	write_coord( position[2] ) 
	write_short( iSprite )			// sprite index
	write_byte( scale)				// scale in 0.1's
	write_byte( alpha )				// brightness
	message_end() 
}



stock Create_StatusIcon(id, status, sprite[], red, green, blue)
{
	message_begin( MSG_ONE, gmsgStatusIcon, {0,0,0}, id ) 
	write_byte( status )			// status 
	write_string( sprite )			// sprite name 
	write_byte( red )				// red 
	write_byte( green )				// green 
	write_byte( blue )				// blue 
	message_end()
}



stock Create_TE_LARGEFUNNEL(position[3], iSprite, flags)
{
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )	
	write_byte( TE_LARGEFUNNEL )
	write_coord( position[0] )		// origin, x
	write_coord( position[1] )		// origin, y
	write_coord( position[2] )		// origin, z
	write_short( iSprite )			// sprite (0 for none)
	write_short( flags )			// 0 for collapsing, 1 for sending outward
	message_end() 
}



stock Create_TE_PLAYERATTACHMENT(id, entity, vOffset, iSprite, life)
{
	message_begin( MSG_ONE, SVC_TEMPENTITY, { 0, 0, 0 }, id )
	write_byte( TE_PLAYERATTACHMENT )
	write_byte( entity )			// entity
	write_coord( vOffset )			// vertical offset ( attachment origin.z = player origin.z + vertical offset )
	write_short( iSprite )			// model index
	write_short( life )				// (life * 10 )
	message_end()
}



stock Create_TE_TELEPORT(position[3])
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY) 
	write_byte( TE_TELEPORT ) 
	write_coord( position[0] ) 
	write_coord( position[1] ) 
	write_coord( position[2] ) 
	message_end()
}



stock Create_TE_LAVASPLASH(position[3])
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY) 
	write_byte( TE_LAVASPLASH ) 
	write_coord( position[0] ) 
	write_coord( position[1] ) 
	write_coord( position[2] ) 
	message_end()
}



stock Create_TE_TAREXPLOSION(position[3])
{
	message_begin( MSG_BROADCAST,SVC_TEMPENTITY) 
	write_byte( TE_TAREXPLOSION ) 
	write_coord( position[0] ) 
	write_coord( position[1] ) 
	write_coord( position[2] ) 
	message_end()
}



stock Create_TE_BUBBLES(start[3], end[3], height, iSprite, count, speed)
{
/*			
	Example:

	g_sBubble = precache_model("sprites/bubble.spr")

	new origin[3], start[3], end[3]

	get_user_origin(victim, origin)

	start[0] = origin[0] - 64
	start[1] = origin[1] - 64
	start[2] = origin[2] - 64

	end[0] = origin[0] + 64
	end[1] = origin[1] + 64
	end[2] = origin[2] + 64

	Create_TE_BUBBLES(start, end, 96, g_sBubble, 100, 8)
*/

	message_begin( MSG_BROADCAST,SVC_TEMPENTITY) 
	write_byte( TE_BUBBLES )
	write_coord( start[0] )				// start position
	write_coord( start[1] ) 
	write_coord( start[2] ) 
	write_coord( end[0] )				// end position
	write_coord( end[1] ) 
	write_coord( end[2] ) 
	write_coord( height )				// float height
	write_short( iSprite )				// Sprite Index
	write_byte( count )					// count
	write_coord( speed )				// speed
	message_end()
}


